🚀 Bài 8: JavaScript Iterables, Sets & Maps

Khám phá các cấu trúc dữ liệu mạnh mẽ trong JavaScript

← Quay lại trang chính

1. 🔄 JavaScript Iterables

Iterables là các đối tượng có thể được duyệt qua (iterated over) bằng for...of loop. Các iterables phổ biến trong JavaScript bao gồm:

  • String - có thể duyệt qua từng ký tự
  • Array - có thể duyệt qua từng phần tử
  • Set - tập hợp các giá trị duy nhất, có thể duyệt qua từng giá trị
  • Map - bộ sưu tập key-value pairs, có thể duyệt qua từng cặp key-value

⚠️ Lưu ý quan trọng:

Object KHÔNG phải là iterable! Bạn không thể sử dụng for...of với Object thông thường. Object cần được chuyển đổi trước khi có thể duyệt qua.

⚠️ Lưu ý quan trọng:

Object KHÔNG phải là iterable! Bạn không thể duyệt qua Object bằng for...of loop. Thay vào đó, sử dụng for...in hoặc Object.keys(), Object.values(), Object.entries().

🔍 Định nghĩa chi tiết:

Set: Là một collection chứa các giá trị duy nhất (unique values). Mỗi giá trị chỉ có thể xuất hiện một lần duy nhất trong Set. Set tự động loại bỏ các giá trị trùng lặp.
Ví dụ: Danh sách ID người dùng, danh sách tags không trùng lặp
Map: Là một collection lưu trữ các cặp key-value, nơi mỗi key là duy nhất và có thể là bất kỳ kiểu dữ liệu nào (không như Object chỉ dùng string/symbol làm key). Map duy trì thứ tự chèn của các phần tử.
Ví dụ: Bảng điểm học sinh (tên → điểm), cache dữ liệu (id → object)

🆚 So sánh Object vs Map vs Iterables:

Object (KHÔNG phải iterable):
  • Key chỉ có thể là string hoặc symbol
  • Không có thuộc tính size
  • Duyệt qua bằng: for...in, Object.keys(), Object.values(), Object.entries()
Map (là iterable):
  • Key có thể là bất kỳ kiểu dữ liệu nào
  • Có thuộc tính size
  • Duyệt qua bằng: for...of, forEach()
  • Duy trì thứ tự chèn
Set (là iterable):
  • Chỉ chứa values (không có keys)
  • Values phải là duy nhất
  • Có thuộc tính size
  • Duyệt qua bằng: for...of, forEach()
iterables-example.js

// Duyệt qua string
const name = "JavaScript";
for (let char of name) {
    console.log(char); // J, a, v, a, S, c, r, i, p, t
}

// Duyệt qua array
const fruits = ["apple", "banana", "orange"];
for (let fruit of fruits) {
    console.log(fruit); // apple, banana, orange
}

// Duyệt qua Set (tập hợp các giá trị duy nhất)
const uniqueNumbers = new Set([1, 2, 2, 3, 3, 4]); // Tự động loại bỏ duplicate
console.log(uniqueNumbers); // Set(4) {1, 2, 3, 4}

for (let number of uniqueNumbers) {
    console.log(number); // 1, 2, 3, 4
}

// Duyệt qua Map (key-value pairs)
const studentGrades = new Map([
    ["Alice", 95],
    ["Bob", 87], 
    ["Charlie", 92]
]);

for (let [student, grade] of studentGrades) {
    console.log(`${student}: ${grade} điểm`); 
    // Alice: 95 điểm
    // Bob: 87 điểm  
    // Charlie: 92 điểm
}

// ❌ Object KHÔNG phải iterable - KHÔNG thể dùng for...of
const student = { name: "John", age: 20, grade: 85 };

// ❌ Cách này SẼ BỊ LỖI!
// for (let item of student) { // TypeError: student is not iterable
//     console.log(item);
// }

// ✅ Cách đúng để duyệt qua Object:
// 1. Dùng for...in để duyệt qua keys
for (let key in student) {
    console.log(`${key}: ${student[key]}`);
}

// 2. Dùng Object.entries() để tạo iterable rồi dùng for...of
for (let [key, value] of Object.entries(student)) {
    console.log(`${key}: ${value}`);
}

// 3. Dùng Object.keys() và Object.values()
for (let key of Object.keys(student)) {
    console.log(`Key: ${key}`);
}

for (let value of Object.values(student)) {
    console.log(`Value: ${value}`);
}

// Kiểm tra xem đối tượng có iterable không
function isIterable(obj) {
    return obj != null && typeof obj[Symbol.iterator] === 'function';
}

console.log(isIterable("Hello")); // true
console.log(isIterable([1, 2, 3])); // true
console.log(isIterable(uniqueNumbers)); // true (Set)
console.log(isIterable(studentGrades)); // true (Map)
console.log(isIterable(student)); // false (Object)
console.log(isIterable(123)); // false
                        

🔍 So sánh Object vs Map vs Set

❌ Object (KHÔNG iterable)
  • Không thể dùng for...of trực tiếp
  • Key phải là string hoặc Symbol
  • Có prototype mặc định
  • Dùng for...in hoặc Object.keys()
✅ Map (Iterable)
  • Có thể dùng for...of
  • Key có thể là bất kỳ kiểu dữ liệu nào
  • Không có prototype
  • Có size property
✅ Set (Iterable)
  • Có thể dùng for...of
  • Chỉ lưu giá trị duy nhất
  • Tự động loại bỏ duplicate
  • Có size property

📝 Cách duyệt qua Object:

const obj = {name: "Long", age: 25, city: "HCM"};

// ❌ SAI - Object không iterable
// for (let item of obj) { ... } // TypeError!

// ✅ ĐÚNG - Các cách duyệt qua Object:
// 1. Duyệt qua keys
for (let key in obj) {
    console.log(key, obj[key]);
}

// 2. Dùng Object.keys()
for (let key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

// 3. Dùng Object.entries()
for (let [key, value] of Object.entries(obj)) {
    console.log(key, value);
}

🎮 Thử ngay: Duyệt qua Iterables

2. 🎯 JavaScript Sets

Set là một collection chứa các giá trị duy nhất (unique values). Mỗi giá trị chỉ có thể xuất hiện một lần trong Set:

sets-example.js

// Tạo Set mới
const mySet = new Set();

// Thêm giá trị vào Set
mySet.add(1);
mySet.add(2);
mySet.add(2); // Không được thêm vì đã tồn tại
mySet.add("hello");

console.log(mySet); // Set(3) {1, 2, "hello"}
console.log(mySet.size); // 3

// Tạo Set từ array (loại bỏ duplicate)
const numbers = [1, 2, 2, 3, 3, 4, 5];
const uniqueNumbers = new Set(numbers);
console.log(uniqueNumbers); // Set(5) {1, 2, 3, 4, 5}

// Chuyển Set về array
const uniqueArray = [...uniqueNumbers];
console.log(uniqueArray); // [1, 2, 3, 4, 5]
                        

🎮 Thử ngay: Tạo Set từ Array

3. ⚙️ JavaScript Set Methods

Set cung cấp nhiều methods hữu ích để thao tác với dữ liệu:

add(value)
set.add(value)
Thêm một giá trị mới vào Set
delete(value)
set.delete(value)
Xóa một giá trị khỏi Set
has(value)
set.has(value)
Kiểm tra xem giá trị có tồn tại trong Set không
clear()
set.clear()
Xóa tất cả giá trị trong Set
forEach()
set.forEach(callback)
Thực thi function cho mỗi giá trị trong Set
values()
set.values()
Trả về iterator chứa tất cả giá trị
set-methods-example.js

const fruits = new Set(["apple", "banana", "orange"]);

// Kiểm tra size
console.log(fruits.size); // 3

// Thêm giá trị
fruits.add("grape");
console.log(fruits); // Set(4) {"apple", "banana", "orange", "grape"}

// Kiểm tra tồn tại
console.log(fruits.has("apple")); // true
console.log(fruits.has("mango")); // false

// Xóa giá trị
fruits.delete("banana");
console.log(fruits); // Set(3) {"apple", "orange", "grape"}

// Duyệt qua Set
fruits.forEach(fruit => {
    console.log(`Tôi thích ${fruit}`);
});

// Sử dụng for...of
for (let fruit of fruits) {
    console.log(fruit);
}
                        

🎮 Thử ngay: Set Methods

4. 🗺️ JavaScript Maps

Map là một collection lưu trữ các cặp key-value. Khác với Object, Map có thể sử dụng bất kỳ kiểu dữ liệu nào làm key:

maps-example.js

// Tạo Map mới
const myMap = new Map();

// Thêm cặp key-value
myMap.set("name", "John");
myMap.set("age", 30);
myMap.set(1, "number key");
myMap.set(true, "boolean key");

console.log(myMap); // Map(4) {"name" => "John", "age" => 30, 1 => "number key", true => "boolean key"}

// Tạo Map từ array
const userMap = new Map([
    ["id", 1],
    ["username", "john_doe"],
    ["email", "john@example.com"]
]);

console.log(userMap.get("username")); // "john_doe"
console.log(userMap.size); // 3

// So sánh Map vs Object
const obj = { name: "Alice", age: 25 };
const map = new Map([["name", "Alice"], ["age", 25]]);

console.log(Object.keys(obj).length); // 2
console.log(map.size); // 2
                        

🎮 Thử ngay: Tạo Map

5. 🔧 JavaScript Map Methods

Map cung cấp nhiều methods mạnh mẽ để thao tác với dữ liệu:

set(key, value)
map.set(key, value)
Thêm hoặc cập nhật một cặp key-value
get(key)
map.get(key)
Lấy giá trị theo key
has(key)
map.has(key)
Kiểm tra xem key có tồn tại không
delete(key)
map.delete(key)
Xóa một cặp key-value
clear()
map.clear()
Xóa tất cả cặp key-value
keys()
map.keys()
Trả về iterator chứa tất cả keys
values()
map.values()
Trả về iterator chứa tất cả values
entries()
map.entries()
Trả về iterator chứa tất cả cặp [key, value]
map-methods-example.js

const studentGrades = new Map();

// Thêm điểm cho học sinh
studentGrades.set("Alice", 95);
studentGrades.set("Bob", 87);
studentGrades.set("Charlie", 92);

console.log(studentGrades.size); // 3

// Lấy điểm của học sinh
console.log(studentGrades.get("Alice")); // 95
console.log(studentGrades.get("David")); // undefined

// Kiểm tra học sinh có tồn tại không
console.log(studentGrades.has("Bob")); // true

// Cập nhật điểm
studentGrades.set("Bob", 90);
console.log(studentGrades.get("Bob")); // 90

// Duyệt qua Map
for (let [name, grade] of studentGrades) {
    console.log(`${name}: ${grade} điểm`);
}

// Sử dụng forEach
studentGrades.forEach((grade, name) => {
    console.log(`${name} đạt ${grade} điểm`);
});

// Lấy tất cả keys và values
console.log([...studentGrades.keys()]); // ["Alice", "Bob", "Charlie"]
console.log([...studentGrades.values()]); // [95, 90, 92]
                        

🎮 Thử ngay: Map Methods

💪 Bài Tập Thực Hành

Áp dụng kiến thức về Iterables, Sets và Maps vào các bài tập thực tế

🎯 Bài 1: Quản lý danh sách unique

Tạo một ứng dụng quản lý danh sách các mục không trùng lặp sử dụng Set.

📊 Bài 2: Bảng điểm học sinh

Sử dụng Map để quản lý điểm số của các học sinh.

🔤 Bài 3: Đếm ký tự trong text

Sử dụng Map để đếm số lần xuất hiện của mỗi ký tự trong một đoạn text.

🛒 Bài 4: Giỏ hàng Shopping

Tạo giỏ hàng sử dụng Map để lưu sản phẩm và số lượng.